/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package entity;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.OneToOne;
import type.InternalStatus;
import type.InvoiceStatus;
import type.InvoiceType;
import type.SalesOrderStatus;
import type.ShippingOrderStatus;

/**
 *
 * @author edd
 */
@Entity(name = "SalesOrder")
public class SalesOrderEntity extends DataObjectEntity implements Serializable {

    private SalesOrderStatus status;
    private InternalStatus internalStatus;
    private double creditPayable;
    private double cashPayable;
    private boolean promotion;
    private double totalPrice;
    private int activeIndex;
    
    private BillingRequestEntity cashPayableAccountedFor;
    
    private SalesOrderStatus backupStatus;

    @ManyToOne
    private CustomerEntity customer;
    @ManyToOne
    private SystemUserEntity systemUser;
    
    @OneToOne (mappedBy="salesOrder")
    private PurchaseOrderEntity purchaseOrder;
    
    @OneToMany(mappedBy = "salesOrder",  cascade = {CascadeType.ALL})
    private Collection<ReservationEntity> reservations;// = new ArrayList<ReservationEntity>();
    //maps sales order to 1 or more reservations
    @OneToMany(mappedBy = "salesOrder")
    private Collection<PlannedReserveEntity> plannedReservation = new ArrayList<PlannedReserveEntity>();
    
    @OneToMany(mappedBy = "salesOrder")
    private Collection<ShippingOrderEntity> shippingOrder = new ArrayList<ShippingOrderEntity>();

    @OneToOne(mappedBy="salesOrder")
    private BackorderEntity backorder;

    @OneToOne(mappedBy="salesOrder")
    private PickListEntity pickList;
    
    @OneToMany(mappedBy="salesOrder")
    private Collection<BillingRequestEntity> billingRequests = new ArrayList<BillingRequestEntity>();
    
    @OneToOne(mappedBy="salesOrder")
    private RefundRequestEntity refundRequest;

    public SalesOrderEntity() {
        super();
        setStatus(SalesOrderStatus.Pending);
        setInternalStatus(InternalStatus.CreditCheckPending);
        setPromotion(false);
        setActiveIndex(0);
        reservations = new ArrayList<ReservationEntity>();
    }

    public SystemUserEntity getSystemUser() {
        return systemUser;
    }

    public void setSystemUser(SystemUserEntity systemUser) {
        this.systemUser = systemUser;
    }

    public BackorderEntity getBackorder() {
        return backorder;
    }

    public void setBackorder(BackorderEntity backorder) {
        this.backorder = backorder;
    }

    public PickListEntity getPickList() {
        return pickList;
    }

    public void setPickList(PickListEntity pickList) {
        this.pickList = pickList;
    }

    public double getCashPayable() {
        return cashPayable;
    }

    public void setCashPayable(double cashPayable) {
        this.cashPayable = cashPayable;
    }

    public double getCreditPayable() {
        return creditPayable;
    }

    public void setCreditPayable(double creditPayable) {
        this.creditPayable = creditPayable;
    }

    public InternalStatus getInternalStatus() {
        return internalStatus;
    }

    public void setInternalStatus(InternalStatus internalStatus) {
        this.internalStatus = internalStatus;
    }

    public Collection<PlannedReserveEntity> getPlannedReservation() {
        return plannedReservation;
    }

    public void setPlannedReservation(Collection<PlannedReserveEntity> plannedReservation) {
        this.plannedReservation = plannedReservation;
    }

    public Collection<ShippingOrderEntity> getShippingOrder() {
        return shippingOrder;
    }

    public void setShippingOrder(Collection<ShippingOrderEntity> shippingOrder) {
        this.shippingOrder = shippingOrder;
    }

    public SalesOrderStatus getStatus() {
        return status;
    }

    public void setStatus(SalesOrderStatus status) {
        this.status = status;
    }

    public Collection<ReservationEntity> getReservations() {
        return reservations;
    }

    public void setReservations(Collection<ReservationEntity> reservations) {
        this.reservations = reservations;
    }

    public CustomerEntity getCustomer() {
        return customer;
    }

    public void setCustomer(CustomerEntity customer) {
        this.customer = customer;
    }

    public PurchaseOrderEntity getPurchaseOrder() {
        return purchaseOrder;
    }

    public void setPurchaseOrder(PurchaseOrderEntity purchaseOrder) {
        this.purchaseOrder = purchaseOrder;
    }

    public Collection<BillingRequestEntity> getBillingRequests() {
        return billingRequests;
    }

    public void setBillingRequests(Collection<BillingRequestEntity> billingRequests) {
        this.billingRequests = billingRequests;
    }

    public boolean isPromotion() {
        return promotion;
    }

    public void setPromotion(boolean promotion) {
        this.promotion = promotion;
    }

    public RefundRequestEntity getRefundRequest() {
        return refundRequest;
    }

    public void setRefundRequest(RefundRequestEntity refundRequest) {
        this.refundRequest = refundRequest;
    }
    
    public boolean isCreditCheckPassed(){
        return !(cashPayable>0);
    }

    public SalesOrderStatus getBackupStatus() {
        return backupStatus;
    }

    public void setBackupStatus(SalesOrderStatus backupStatus) {
        this.backupStatus = backupStatus;
    }
    
    public String getCreditCheckStatus(){
        if(!getCustomer().getHasAccount())
            return "cannot be performed because customer hasn't been assigned an account yet!";
        
        if(isCreditCheckPassed())
            return "Passed";
        else
            return "Failed";
    }

    @Override
    public String childToString() {
        return "SalesOrderEntity{" + "status=" + status + ", internalStatus=" + internalStatus + ", creditPayable=" + creditPayable + ", cashPayable=" + cashPayable + ", promotion=" + promotion + ", customer=" + customer + ", systemUser=" + systemUser + ", purchaseOrder=" + purchaseOrder + ", reservations=" + reservations + ", plannedReservation=" + plannedReservation + ", shippingOrder=" + shippingOrder + ", backorder=" + backorder + ", pickList=" + pickList + ", billingRequests=" + billingRequests + ", refundRequest=" + refundRequest + '}';
    }

    public double getTotalPrice() {
        return totalPrice;
    }

    public void setTotalPrice(double totalPrice) {
        this.totalPrice = totalPrice;
    }

    public BillingRequestEntity getCashPayableAccountedFor() {
        return cashPayableAccountedFor;
    }

    public void setCashPayableAccountedFor(BillingRequestEntity cashPayableAccountedFor) {
        this.cashPayableAccountedFor = cashPayableAccountedFor;
    }
    
    public boolean hasOutstandingInvoice(){
        boolean pending = false;
        double totalPaid = 0.0;
        
        for(BillingRequestEntity request : billingRequests){
            
            if(request.getInvoice()==null || request.getInvoice().getStatus()!=InvoiceStatus.paid){
                pending = true;
                break;
            }else{
                if(request.getInvoice().getType()!=InvoiceType.reminder)
                    totalPaid += request.getInvoice().getAmount();
                else
                    totalPaid += (request.getInvoice().getAmount()-request.getInvoice().getLatePenalty());
            }
        }
        
        if(totalPaid<(cashPayable+creditPayable))
            pending = true;
        
        return pending;
    }
    
    public boolean allShipmentsFulfilled(){
        boolean fulfilled = true;
        if(shippingOrder==null){
            fulfilled = false;
            return fulfilled;
        }
        for(ShippingOrderEntity s : shippingOrder){
            if(s.getStatus()!=ShippingOrderStatus.fulfilled){
                fulfilled = false;
                break;
            }
        }   
        
        return fulfilled;
    }

    public int getActiveIndex() {
        int activeIndex = 0;
        
        if (this.internalStatus.equals(InternalStatus.ProvideLeadTimePending))
            activeIndex = 1;
        if (this.internalStatus.equals(InternalStatus.CustomerReviewPending))
            activeIndex = 2;
        if (this.internalStatus.equals(InternalStatus.DeliveryPending))
            activeIndex = 3;
        if (this.internalStatus.equals(InternalStatus.BillingRequestPending) 
                || this.internalStatus.equals(InternalStatus.BillingConfirmaPending) 
                || this.internalStatus.equals(InternalStatus.PaymentPending))
            activeIndex = 4;
        if (this.internalStatus.equals(InternalStatus.PaymentComplete))
            activeIndex = 5;
            
        return activeIndex;
    }

    public void setActiveIndex(int activeIndex) {
        this.activeIndex = activeIndex;
    }

}
